local function OnStartBundling(inst)
    inst.components.stackable:Get():Remove()
end

local function MakeWrap(name, containerprefab)
    local assets =
    {
        Asset("ANIM", "anim/bundle.zip"),
    }

    local prefabs =
    {
        "bboy_lost_package",
        containerprefab,
    }

    local function fn()
        local inst = CreateEntity()

        inst.entity:AddTransform()
        inst.entity:AddAnimState()
        inst.entity:AddNetwork()

        MakeInventoryPhysics(inst)

        inst.AnimState:SetBank("bundle")
        inst.AnimState:SetBuild("bundle")
        inst.AnimState:PlayAnimation("idle")

        inst.entity:SetPristine()
        if not TheWorld.ismastersim then
            return inst
        end

        inst:AddComponent("stackable")
        inst.components.stackable.maxsize = TUNING.STACK_SIZE_MEDITEM

        inst:AddComponent("inspectable")
        inst:AddComponent("inventoryitem")
        inst.components.inventoryitem:ChangeImageName("bundlewrap")
        inst.components.inventoryitem:SetSinks(true)

        inst:AddComponent("bundlemaker")
        inst.components.bundlemaker:SetBundlingPrefabs(containerprefab, name)
        inst.components.bundlemaker:SetOnStartBundlingFn(OnStartBundling)

        inst:AddComponent("fuel")
        inst.components.fuel.fuelvalue = TUNING.MED_FUEL

        MakeSmallBurnable(inst, TUNING.SMALL_BURNTIME)
        MakeSmallPropagator(inst)
        inst.components.propagator.flashpoint = 10 + math.random() * 5
        MakeHauntableLaunchAndIgnite(inst)

        return inst
    end

    return Prefab(name .. "wrap", fn, assets, prefabs)
end

local function ChoosePackageLoot()
    local results = {
        { "bboy_zhongyuan_blueprint", 1 }, -- 中元节蓝图保底
    }

    local other_items = {
        { prefab = "bboy_nether_moth",         count = 5, chance = 0.75 },
        { prefab = "waxpaper",                 count = 5, chance = 0.75 },
        { prefab = "beeswax",                  count = 5, chance = 0.75 },
        { prefab = "bboy_jia_blueprint",       count = 1, chance = 0.75 },
        { prefab = "miniflare",                count = 1, chance = 0.75 },
        { prefab = "orangestaff",              count = 1, chance = 0.20 },
        { prefab = "yellowstaff",              count = 1, chance = 0.20 },
        { prefab = "walrushat",                count = 1, chance = 0.20 },
        { prefab = "nightmare_timepiece",      count = 1, chance = 0.20 },
        { prefab = "bboy_zhongyuan_blueprint", count = 1, chance = 0.05 },
        { prefab = "panflute",                 count = 1, chance = 0.05 },
        { prefab = "saddle_race",              count = 1, chance = 0.05 },
        { prefab = "krampus_sack",             count = 1, chance = 0.05 },
    }

    local max_types = 4
    local used_items = {}      -- 已尝试过的
    local remaining_items = {} -- 当前未被筛选尝试的
    for _, v in ipairs(other_items) do
        table.insert(remaining_items, v)
    end

    local function random_pick_n(from_list, n)
        local out = {}
        for _ = 1, math.min(n, #from_list) do
            local i = math.random(#from_list)
            table.insert(out, table.remove(from_list, i))
        end
        return out
    end

    local function try_add_items(pick_list)
        local added = 0
        for _, item in ipairs(pick_list) do
            table.insert(used_items, item)
            if #results < max_types and math.random() < item.chance then
                table.insert(results, { item.prefab, item.count })
                added = added + 1
            end
        end
        return added
    end

    -- 第一轮：随机选 3 种未尝试物品尝试打包
    try_add_items(random_pick_n(remaining_items, 3))

    -- 后续轮次：从剩下未尝试过的里，根据剩余空位数，逐轮筛选再尝试打包
    while #results < max_types and #remaining_items > 0 do
        local needed = max_types - #results
        local pick_num = math.min(needed, math.min(#remaining_items, 3))
        try_add_items(random_pick_n(remaining_items, pick_num))
    end

    return results
end

local function OnInitLoot(inst)
    local items = ChoosePackageLoot()
    local bundled = {}
    for _, entry in ipairs(items) do
        local item = SpawnPrefab(entry[1])
        if item ~= nil and item.components.stackable ~= nil and entry[2] > 1 then
            item.components.stackable:SetStackSize(entry[2])
        end
        table.insert(bundled, item)
    end
    inst.components.unwrappable:WrapItems(bundled)
    for _, item in ipairs(bundled) do
        item:Remove()
    end
end

local function MakeBundle(loot, setupdata)
    local assets =
    {
        Asset("ANIM", "anim/bboy_lost_package.zip"),
    }

    local prefabs =
    {
        "ash",
        "bundle_unwrap",
    }

    if loot ~= nil then
        for _, v in ipairs(loot) do
            table.insert(prefabs, v)
        end
    end

    local function OnWrapped(inst, num, doer)
        inst.AnimState:PlayAnimation("idle")

        if doer ~= nil and doer.SoundEmitter ~= nil then
            doer.SoundEmitter:PlaySound("dontstarve/common/together/packaged")
        end
    end

    local function OnUnwrapped(inst, pos, doer)
        if inst.burnt then
            SpawnPrefab("ash").Transform:SetPosition(pos:Get())
        else
            -- 这个部分是解包时掉落物品的逻辑,不包括打包在打包纸里的物品
            local loottable = (setupdata ~= nil and setupdata.lootfn ~= nil) and setupdata.lootfn(inst, doer) or loot
            if loottable ~= nil then
                local moisture = inst.components.inventoryitem:GetMoisture()
                local iswet = inst.components.inventoryitem:IsWet()
                for i, v in ipairs(loottable) do
                    local item = SpawnPrefab(v)
                    if item ~= nil then
                        if item.Physics ~= nil then
                            item.Physics:Teleport(pos:Get())
                        else
                            item.Transform:SetPosition(pos:Get())
                        end
                        if item.components.inventoryitem ~= nil then
                            item.components.inventoryitem:InheritMoisture(moisture, iswet)
                        end
                    end
                end
            end
            SpawnPrefab("bundle_unwrap").Transform:SetPosition(pos:Get())
        end
        if doer ~= nil and doer.SoundEmitter ~= nil then
            doer.SoundEmitter:PlaySound("dontstarve/common/together/packaged")
        end
        inst:Remove()
    end

    local function fn()
        local inst = CreateEntity()

        inst.entity:AddTransform()
        inst.entity:AddAnimState()
        inst.entity:AddNetwork()

        MakeInventoryPhysics(inst)

        inst.AnimState:SetBank("bboy_lost_package")
        inst.AnimState:SetBuild("bboy_lost_package")
        inst.AnimState:PlayAnimation("idle")

        inst:AddTag("bundle")

        inst:AddTag("unwrappable")

        if setupdata.peekcontainer then
            inst:AddTag("canpeek")
        end

        if setupdata ~= nil and setupdata.common_postinit ~= nil then
            setupdata.common_postinit(inst, setupdata)
        end

        MakeInventoryFloatable(inst, "med", nil, 0.55)

        inst.entity:SetPristine()

        if not TheWorld.ismastersim then
            return inst
        end

        inst:AddComponent("inspectable")

        inst:AddComponent("inventoryitem")

        inst:AddComponent("unwrappable")
        inst.components.unwrappable:SetOnWrappedFn(OnWrapped)
        inst.components.unwrappable:SetOnUnwrappedFn(OnUnwrapped)
        inst.components.unwrappable:SetPeekContainer(setupdata.peekcontainer)

        -- 打包初始物品
        OnInitLoot(inst)

        MakeHauntableLaunchAndIgnite(inst)

        if setupdata ~= nil and setupdata.master_postinit ~= nil then
            setupdata.master_postinit(inst, setupdata)
        end

        return inst
    end

    return Prefab("bboy_lost_package", fn, assets, prefabs)
end

local bboy_lost_package =
{
    -- common_postinit = function(inst, setupdata)
    --     inst.SCANNABLE_RECIPENAME = "bundlewrap" -- 女工扫描仪扫描后解锁制作的物品,此mod物品不需要
    -- end,
    peekcontainer = "bundle_container", -- 窥视容器
}

return
    MakeBundle({ "papyrus" }, bboy_lost_package),
    -- 本mod没有打包袋的获取方式,用官方的贴图动画数据,考虑到兼容性所以预留了对应的打包袋预制体,功能和官方保持一致,贴图动画资源也一致
    MakeWrap("bboy_lost_package", "bundle_container")
